functor Env () : ENV =
struct

  structure Err = ErrorMsg 

  type key = string
  
  datatype types
    = Simple
    | Struct of key
    | Array of int * types 
    | Pointer of types

  type 'b env = (key * 'b) list

  type 'b struct_env =  (int * ('b env)) env

  fun creat () = []
  fun creatse () = []

  fun lookup v [] = NONE
    | lookup v ((u, inf):: l) =
      if v = u
      then SOME inf
      else lookup v l

  fun getSSize v senv =
      let val xopt = lookup v senv
          val (size, _) = case xopt
                           of NONE => raise Fail "There is no such structure!" 
                            | SOME a => a
      in  size
      end
 
  fun calTypeSize ty senv =
      case ty
       of Simple => 4
        | Array (i, subtype) =>
      	  let val elemsize = calTypeSize subtype senv
          in  i * elemsize
          end
        | Pointer ty1 => 4
        | Struct id => (getSSize id senv) handle Option => raise Fail "compiler bug\n"

  fun lookupFL s env =
      let val elemOpt = lookup s env
          val (size, fields) = case elemOpt
                                of  NONE => raise Fail "no such structure"
                                  | SOME e => e
      in  fields
      end

  fun lookupF s id env =
      let val (size, fields) = Option.valOf(lookup s env)
      in  lookup id fields
      end handle Option => raise Fail "compiler bug\n"
      
  fun enter id inf env = (id,inf)::env

  fun enterS id size fieldlist  env = enter id (size, fieldlist) env

  fun fromList (l : (key * 'b) list) : 'b env = 
      case l
       of [] => creat()
        | (k, i) :: xs => enter k i (fromList xs)
        
  fun toList (e : 'b env) : (key * 'b) list = 
      case e 
       of [] => []
        | (k, i) :: xs => (k, i) :: (toList xs)

  fun transSenv (f2 : 'b -> 'c, senv : 'b struct_env) = 
      let fun mapElem subenv = 
              let fun f2' (s, inf) = f2 inf
                  val newsubenv = toList subenv
              in  List.map f2' newsubenv
              end
          val senvl = toList senv
          fun mapSenv (str, (i, subenv)) =
              (str, mapElem subenv)
      in  List.map mapSenv senvl
      end
end
